package top.lyjwn.todo.weinxin.mch;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import top.lyjwn.todo.common.utils.RandomValue;
import top.lyjwn.todo.weinxin.WXPayConfig;
import top.lyjwn.todo.weinxin.mch.controller.PayController;
import top.lyjwn.todo.weinxin.mch.pay.WXPay;
import top.lyjwn.todo.weinxin.param.WXPayParam;
import top.lyjwn.todo.weinxin.utils.SignUtil;

import top.lyjwn.todo.weinxin.data.mch.*;
import top.lyjwn.todo.weinxin.data.mch.param.*;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 微信商户
 *
 * @author luoyujie
 */
@Component
public class WXMch {


    @Autowired
    private WXPay wxPay;

    @Autowired
    private WXPayParam wxPayParam;

    @Autowired
    private SignUtil signUtil;

    /**
     * 统一下单
     *
     * @param description 商品描述
     * @param orderId     订单号
     * @param total_fee   总价格
     * @param ip          下单设备ip
     * @return
     */
    public UnifiedOrderResult unifiedOrder(String openid, String description, String orderId, Integer total_fee,
                                           String ip) {
        UnifiedOrder unifiedOrder = new UnifiedOrder(wxPayParam.getAppid(),wxPayParam.getMchId(),RandomValue.getRandomString(32), description, orderId, total_fee,
                ip, wxPayParam.getDomainName() + PayController.CONTROLLER_NAME + PayController.PAY_NOTIFY_PATH, "JSAPI");
        unifiedOrder.setOpenid(openid);
        unifiedOrder.setSign_type("HMAC-SHA256");
        String sign = signUtil.getSign(unifiedOrder);
        unifiedOrder.setSign(sign);
        UnifiedOrderResult unifiedOrderResult = wxPay.unifiedOrderApi(unifiedOrder);
        return unifiedOrderResult;
    }

    public UnifiedOrderResult unifiedOrder(String openid, String description, String orderId, Integer total_fee,
                                           String ip, String attach) {
        UnifiedOrder unifiedOrder = new UnifiedOrder(wxPayParam.getAppid(),wxPayParam.getMchId(),RandomValue.getRandomString(32), description, orderId, total_fee,
                ip, wxPayParam.getDomainName() + PayController.CONTROLLER_NAME + PayController.PAY_NOTIFY_PATH, "JSAPI");
        unifiedOrder.setAttach(attach);
        unifiedOrder.setOpenid(openid);
        unifiedOrder.setSign_type("HMAC-SHA256");
        String sign = signUtil.getSign(unifiedOrder);
        unifiedOrder.setSign(sign);
        UnifiedOrderResult unifiedOrderResult = wxPay.unifiedOrderApi(unifiedOrder);
        return unifiedOrderResult;
    }


    /**
     * 统一下单
     *
     * @param description 商品描述
     * @param orderId     订单号
     * @param total_fee   总价格
     * @param ip          下单设备ip
     * @param attach      附加数据
     * @param notify_url  通知url
     * @return
     */
    public UnifiedOrderResult unifiedOrder(String openid, String description, String orderId, Integer total_fee,
                                           String ip, String attach, String notify_url) {
        UnifiedOrder unifiedOrder = new UnifiedOrder(wxPayParam.getAppid(),wxPayParam.getMchId(), RandomValue.getRandomString(32), description, orderId, total_fee,
                ip, notify_url, "JSAPI");
        unifiedOrder.setAttach(attach);
        unifiedOrder.setOpenid(openid);
        unifiedOrder.setSign_type("HMAC-SHA256");
        String sign = signUtil.getSign(unifiedOrder);
        unifiedOrder.setSign(sign);
        UnifiedOrderResult unifiedOrderResult = wxPay.unifiedOrderApi(unifiedOrder);
        return unifiedOrderResult;
    }

    /**
     * 查询订单
     *
     * @param orderId 订单号
     * @return
     */
    public QueryOrderResult queryOrder(String orderId) {
        QueryOrder queryOrder = new QueryOrder(wxPayParam.getAppid(),wxPayParam.getMchId(),orderId, RandomValue.getRandomString(32));
        String sign = signUtil.getSign(queryOrder);
        queryOrder.setSign(sign);
        QueryOrderResult queryOrderResult = wxPay.queryOrderApi(queryOrder);
        return queryOrderResult;
    }

    /**
     * 关闭订单
     *
     * @param orderId 订单号
     * @return
     */
    public CloseOrderResult closeOrder(String orderId) {
        CloseOrder closeOrder = new CloseOrder(wxPayParam.getAppid(),wxPayParam.getMchId(),orderId, RandomValue.getRandomString(32));
        String sign = signUtil.getSign(closeOrder);
        closeOrder.setSign(sign);
        CloseOrderResult closeOrderResult = wxPay.closeOrderApi(closeOrder);
        return closeOrderResult;
    }




    /**
     * 申请退款
     *
     * @param orderId    订单号
     * @param total_fee  总金额
     * @param refund_fee 退款金额
     * @return
     */
    public ApplyRefundResult applyRefund(String orderId, Integer total_fee, Integer refund_fee) {
        return applyRefund(orderId, total_fee, refund_fee, wxPayParam.getDomainName() + PayController.CONTROLLER_NAME + PayController.REFUND_NOTIFY_PATH);
    }


    /**
     * 申请退款
     *
     * @param orderId    订单号
     * @param total_fee  总金额
     * @param refund_fee 退款金额
     * @param notify_url 通知url
     * @return
     */
    public ApplyRefundResult applyRefund(String orderId, Integer total_fee, Integer refund_fee, String notify_url) {
        ApplyRefund applyRefund = new ApplyRefund(wxPayParam.getAppid(),wxPayParam.getMchId(),orderId, total_fee, refund_fee);
        applyRefund.setNotify_url(notify_url);
        String sign = signUtil.getSign(applyRefund);
        applyRefund.setSign(sign);
        ApplyRefundResult result = wxPay.applyRefundApi(applyRefund);
        return result;
    }


    /**
     * 申请退款
     *
     * @param orderId       订单号
     * @param total_fee     总金额
     * @param out_refund_no 退款订单号
     * @return
     */
    public ApplyRefundResult applyRefund(String orderId, Integer total_fee, String out_refund_no) {
        return applyRefund(orderId, total_fee, total_fee, wxPayParam.getDomainName() + PayController.CONTROLLER_NAME + PayController.REFUND_NOTIFY_PATH, out_refund_no);
    }


    /**
     * 申请退款
     *
     * @param orderId       订单号
     * @param total_fee     总金额
     * @param refund_fee    退款金额
     * @param notify_url    通知url
     * @param out_refund_no 退款订单号
     * @return
     */
    public ApplyRefundResult applyRefund(String orderId, Integer total_fee, Integer refund_fee, String notify_url, String out_refund_no) {
        ApplyRefund applyRefund = new ApplyRefund(wxPayParam.getAppid(),wxPayParam.getMchId(),orderId, total_fee, refund_fee, out_refund_no);
        applyRefund.setNotify_url(notify_url);
        String sign = signUtil.getSign(applyRefund);
        applyRefund.setSign(sign);
        ApplyRefundResult result = wxPay.applyRefundApi(applyRefund);
        return result;
    }


    /**
     * 申请退款
     *
     * @param orderId    订单号
     * @param total_fee  总金额
     * @param refund_fee 退款金额
     * @param out_refund_no 退款订单号
     * @param desc       退款原因
     * @return
     */
    public ApplyRefundResult applyRefundAtt(String orderId, Integer total_fee, Integer refund_fee,String out_refund_no, String desc) {
        ApplyRefund applyRefund = new ApplyRefund(wxPayParam.getAppid(),wxPayParam.getMchId(),orderId, total_fee, refund_fee,out_refund_no);
        applyRefund.setNotify_url(wxPayParam.getDomainName() + PayController.CONTROLLER_NAME + PayController.REFUND_NOTIFY_PATH);
        applyRefund.setRefund_desc(desc);
        String sign = signUtil.getSign(applyRefund);
        applyRefund.setSign(sign);
        ApplyRefundResult result = wxPay.applyRefundApi(applyRefund);
        return result;
    }

    /**
     * 查询退款
     *
     * @param orderId 订单号
     * @return
     */
    public QueryRefundResult queryRefund(String orderId) {
        //QueryRefund queryRefund = new QueryRefund(orderId, RandomValue.getRandomString(32));
        QueryRefund queryRefund = new QueryRefund(wxPayParam.getAppid(),wxPayParam.getMchId(),RandomValue.getRandomString(32));
        queryRefund.setOut_trade_no(orderId);
        String sign = signUtil.getSign(queryRefund);
        queryRefund.setSign(sign);
        QueryRefundResult result = wxPay.queryRefundApi(queryRefund);
        return result;
    }

    public enum QueryRefundType {
        transaction_id, out_trade_no, out_refund_no, refund_id
    }


    /**
     * @param nno             未知的传入号
     * @param queryRefundType 传入号类型
     * @return
     */
    public QueryRefundResult queryRefund(String nno, QueryRefundType queryRefundType) {
        QueryRefund queryRefund = new QueryRefund(wxPayParam.getAppid(),wxPayParam.getMchId(),RandomValue.getRandomString(32));
        switch (queryRefundType) {
            case refund_id:
                queryRefund.setRefund_id(nno);
                break;
            case out_trade_no:
                queryRefund.setOut_trade_no(nno);
                break;
            case out_refund_no:
                queryRefund.setOut_refund_no(nno);
                break;
            case transaction_id:
                queryRefund.setTransaction_id(nno);
                break;
            default:
                queryRefund.setRefund_id(nno);
                break;
        }
        String sign = signUtil.getSign(queryRefund);
        queryRefund.setSign(sign);
        QueryRefundResult result = wxPay.queryRefundApi(queryRefund);
        return result;
    }

    /**
     * 下载对账单
     *
     * @param bill_date 对账单日期
     * @return
     */
    public DownloadBillResult downloadBill(Date bill_date, String bill_type) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dateformat = sdf.format(bill_date);
        DownloadBill downloadBill = new DownloadBill(wxPayParam.getAppid(),wxPayParam.getMchId(),RandomValue.getRandomString(32), dateformat);
        downloadBill.setBill_type(bill_type);
        String sign = signUtil.getSign(downloadBill);
        downloadBill.setSign(sign);
        DownloadBillResult result = wxPay.downloadBillApi(downloadBill);
        return result;
    }

    /**
     * 下载资金账单
     *
     * @param bill_date    资金账单日期
     * @param account_type 资金账户类型 账单的资金来源账户：
     *                     <p>
     *                     Basic 基本账户
     *                     <p>
     *                     Operation 运营账户
     *                     <p>
     *                     Fees 手续费账户
     * @return
     */
    public DownloadFundFlowResult downloadFundFlowApi(Date bill_date, String account_type) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dateformat = sdf.format(bill_date);
        DownloadFundFlow downloadFundFlow = new DownloadFundFlow(wxPayParam.getAppid(),wxPayParam.getMchId(),RandomValue.getRandomString(32), dateformat,
                account_type);
        String sign = signUtil.getSign(downloadFundFlow);
        downloadFundFlow.setSign(sign);
        DownloadFundFlowResult result = wxPay.downloadFundFlowApi(downloadFundFlow);
        return result;
    }

    /**
     * 交易保障
     *
     * @param interface_url 接口URL
     * @param execute_time  接口耗时
     * @param return_code   返回状态码
     * @param return_msg    返回信息
     * @param result_code   业务结果
     * @param user_ip       访问接口IP
     * @return
     */
    public ReportResult reportApi(String interface_url, long execute_time, String return_code, String return_msg,
                                  String result_code, String user_ip) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String time = sdf.format(new Date());
        Report report = new Report(wxPayParam.getAppid(),wxPayParam.getMchId(),RandomValue.getRandomString(32), interface_url, String.valueOf(execute_time),
                return_code, return_msg, result_code, user_ip, time);
        String sign = signUtil.getSign(report);
        report.setSign(sign);
        ReportResult result = wxPay.reportApi(report);
        return result;
    }

    /**
     * 拉取订单评价
     *
     * @param begin_time 开始时间
     * @param end_time   结束时间
     * @param offset     索引位置
     * @return
     */
    public BatchQueryCommentResult batchQueryCommentApi(Date begin_time, Date end_time, long offset) {
        return this.batchQueryCommentApi(begin_time, end_time, offset, 200);
    }

    /**
     * 拉取订单评价
     *
     * @param begin_time 开始时间
     * @param end_time   结束时间
     * @param offset     索引位置
     * @param limit      取多少
     * @return
     */
    public BatchQueryCommentResult batchQueryCommentApi(Date begin_time, Date end_time, long offset, Integer limit) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        BatchQueryComment batchQueryComment = new BatchQueryComment(wxPayParam.getAppid(),wxPayParam.getMchId(),RandomValue.getRandomString(32),
                sdf.format(begin_time), sdf.format(end_time), offset);
        batchQueryComment.setLimit(limit);
        String sign = signUtil.getSign(batchQueryComment);
        batchQueryComment.setSign(sign);
        BatchQueryCommentResult result = wxPay.batchQueryCommentApi(batchQueryComment);
        return result;
    }
}
